iT邦幫忙

2022 iThome 鐵人賽

DAY 8
0
Modern Web

React Hook 不求人,建立自己的 Hook Libary系列 第 8

[DAY 08] 自己的Hook自己做!useToggle 讓你想開就開,想關就關

  • 分享至 

  • xImage
  •  

終於進入正題啦!

情境

不論是現實世界還是網路上,小朋友看到東西都喜歡碰一下摸一下(手賤),只要能互動就會興奮到一個不行,特別是能開開關關的東西,一不小心就會被玩壞家長就要來賠錢,還好,我們做的是網頁。

最常遇到的功能無非就是 Drawre / Modal / Dialog / Accordion / Animaiton 任何你想到需要狀態來切換開關的通通都用得到,今天就來刻個 useToogle 吧!

功能與描述

useToggle 無非就是開關,切換 truefalse 之間,非常簡單。

我們需要:

  • 能知道現在是開還是關的 state
  • 能讓開變關、關變開,切換用的 toggle

額外的行前準備

之後的 DEMO 會使用 Chakra-UI 的元件來搭配我們自己刻的 Hook 一同產出

嘗試最低限度的試玩 Remix 以及 mdx 來產出 demo-site 以及文件

藉這個機會接觸不同的東西來提(ㄋㄩㄝˋ)升(ㄉㄞˋ)自己 (/‵Д′)/~ ╧╧

開始!

DEMO-SITE 在這裡

畫面

最常見到的就是一顆按鈕打開一個小框框的功能:

function Example() {
  return (
    <>
      <Button/>
      <Modal />
    </>
  )
}

Button 與 Modal 都是 Chakra-UI的元件,上面的 code 縮減很多內容,只要知道會有一顆按鈕跟一個Modal就好 XD

建立 useToggle

按照需求,需要一個 useState,並 return 相關的內容:

function useToggle() {
  const [state, setState] = useState(false)

  return [state, toggle]
}

//如果你想要 return object 也可以
return {state, toggle}

切換用的 toggle

const toggle = () => setState((prev) => !prev)

整體會是這樣:

function useToggle(defaultState = false) {
  const [state, setState] = useState(defaultState)

  const toggle = () => setState((prev) => !prev)

  return [state, toggle]
}

加進來

function Example() {
  const [isOpen, toggle] = useToggle()
  return (
    <>
      <Button onClick={toggle}>TOGGLE</Button>
      <Modal isOpen={isOpen} onClose={toggle} isCentered>
        <ModalOverlay />
        <ModalContent>
          <ModalHeader>Hello (´・ω・`)</ModalHeader>
          <ModalCloseButton />

          <ModalFooter>
            <Button colorScheme="blue" mr={3} onClick={toggle}>
              Close
            </Button>
          </ModalFooter>
        </ModalContent>
      </Modal>
    </>
  )
}
  • <Button /> 用來打開 Modal
  • <Modal /> 本身接受 isOpen 來告訴它要不要打開
  • <Modal /> 本身也接受 onClose 來觸發關掉的動作
  • Modal 裡面的 <Button /> 也是觸發關掉的動作

這樣一來就完成啦!

加入更多魔法(?

  • 可以接受一個 defaultValue,並預設為 false
function useToggle(defaultState = false) {
  const [state, setState] = useState(defaultState)
  //略
}
  • 可以再加入型別判斷,使這個 Hook 更加嚴謹 (optional)
function useToggle(defaultState = false) {
  if(typeof defaultState !== 'boolean') {
    throw new Error("UseToggle: defaultState should be Boolean")
  }
  
  const [state, setState] = useState(defaultState)

  const toggle = () => setState((prev) => !prev)

  return [state, toggle]
}
  • 加入 useCallback (optional)
function useToggle(defaultState = false) {
  if(typeof defaultState !== 'boolean') {
    throw new Error("UseToggle: defaultState should be Boolean")
  }
  
  const [state, setState] = useState(defaultState)

  const toggle = useCallback(() => setState((prev) => !prev),[])

  return [state, toggle]
}

結語

其實還沒完,儘管一開始我們知道接下來狀態一定會變 true (or false),但這樣的 toggle 乍看下其實很難知道要從什麼狀態變成什麼狀態,而且未來也不確定會不會再塞幾百行的code 與 side effect(?),下一篇再來進一步擴充吧!


上一篇
[DAY 07] 三個你不能不知道的 Hook 小知識!
下一篇
[DAY 09] 自己的Hook自己做!useToggle 再進化,useToggle+!
系列文
React Hook 不求人,建立自己的 Hook Libary30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言